using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using Path = System.IO.Path;


namespace BearUtil
{
    public enum DisplayRange
    {
        All,
        DenpendenicesOnly
    }

    /// <summary>
    /// AA group 资源，依赖检索工具
    /// </summary>
    [InlineEditor]
    public class AAAssetsDependenciesCheckTool : BearScriptableObject
    {
        /// <summary>
        /// 固定生成路径
        /// </summary>
        public override string DefaultPath
        {
            get => "Assets/AAAssetsDependenciesCheckTool.asset";
        }
        
        /// <summary>
        /// 数据对比缓存，暂时没用
        /// </summary>
        public string CacheDataPath
        {
            get => "Assets/AAAssetsDependenciesCache/Cache.byte";
        }
        
        [InfoBox("用于检测不同的 Group 中资源相互依赖问题依赖")]
        [LabelText("显示范围：1. 全部 2. 仅展示依赖不在包内")] public DisplayRange type = DisplayRange.All;

        /// <summary>
        /// 单例对象，快速获取
        /// </summary>
        private static AAAssetsDependenciesCheckTool _instance;

        public static AAAssetsDependenciesCheckTool Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = Init();
                }

                return _instance;
            }
        }

        // 用于Tools 手动创建对象，前期测试使用
        [MenuItem("Tools/BearTool/Dependencies Check Tool")]
        private static void menuOption()
        {
            generate<AAAssetsDependenciesCheckTool>();
        }

        /// <summary>
        /// 初始化，新工具可以按照这个模板来重新写
        /// </summary>
        /// <returns></returns>
        public static AAAssetsDependenciesCheckTool Init()
        {
            var instance = CreateInstance<AAAssetsDependenciesCheckTool>();
            instance = AssetDatabase.LoadAssetAtPath<AAAssetsDependenciesCheckTool>(instance.DefaultPath);
            if (instance == null)
            {
                menuOption();
                instance = AssetDatabase.LoadAssetAtPath<AAAssetsDependenciesCheckTool>(instance.DefaultPath);
            }

            _instance = instance;

            return instance;
        }
        
      
        [TableList]
        public List<SearchedAAGroup> results = new List<SearchedAAGroup>();
        private AddressableAssetSettings setting;
        
        /// <summary>
        /// 执行测试
        /// </summary>
        [Button("执行检测", ButtonSizes.Gigantic)]
        public void Execute()
        {
            if (results == null)
                results = new List<SearchedAAGroup>();
            results.Clear();

            setting = AAManagementUtils.GetSettings();
            for (var i = 0; i < setting.groups.Count; i++)
            {
                var group = setting.groups[i];
                checkEntries(group);
            }
        }
            
        private void checkEntries(AddressableAssetGroup group)
        {
            var owner = new SearchedAAGroup();
            owner.groupName = group.name;
            owner.entries = new List<EntryElement>();

            // 复合体
            var complexus = group.entries.Where((e) =>
            {
                var ext = Path.GetExtension(e.AssetPath);
                return ext.Equals(".prefab") || ext.Equals(".spriteatlas") || ext.Equals(".controller");
            }).ToList();
                    
            for (var j = 0; j < complexus.Count; j++)
            {
                var entry = complexus[j];
                var dependencies = AssetDatabase.GetDependencies(entry.AssetPath);

                for (int k = 0; k < dependencies.Length; k++)
                {
                    var guid = AssetDatabase.AssetPathToGUID(dependencies[k]);
                    var depGroup = setting.FindDepGroupByGuid(guid);
                    if (depGroup != null && depGroup != group)
                    {
                        var asset = AssetDatabase.LoadAssetAtPath<Object>(dependencies[k]);
                        var element = new EntryElement(asset, depGroup);
                        owner.entries.Add(element);
                    }
                }
            }
            
            if (owner.entries.Count > 0)
                results.Add(owner);
        }
    }


    /// <summary>
    /// 检测存储数据
    /// 优先检查单个 group
    /// group 是否依赖外部资源
    /// 相关资源
    /// 相关资源当前存在 group
    /// 
    /// </summary>
    [SerializeField]
    public class SearchedAAGroup
    {
        public string groupName;
        [HideInInspector]
        public Hash128 hash;
        [TableList]
        public List<EntryElement> entries;
    }

    /// <summary>
    /// 被检测资源数据
    /// </summary>
    ///
    [SerializeField]
    public class EntryElement
    {
        [ReadOnly, LabelText("资源名称")] public string AssetName;
        [ReadOnly, LabelText("依赖包名")] public string GroupName;

        private Object asset;
        private AddressableAssetGroup owner;

        public EntryElement(Object asset, AddressableAssetGroup group)
        {
            SetData(asset, group);
        }

        /// <summary>
        /// 设置数据
        /// </summary>
        /// <param name="asset"></param>
        /// <param name="group"></param>
        public void SetData(Object asset, AddressableAssetGroup group)
        {
            this.asset = asset;
            this.owner = group;

            AssetName = asset.name;
            GroupName = group.name;
        }
    }

    /// <summary>
    /// 依赖数据判断，缓存数据，用于重新检测
    /// </summary>
    public class DependData
    {
        
    }
}